import logging
import random
import numpy as np
import matplotlib.pyplot as plt

from util.util_log import setup_logging
from util.util_csv import save_csv
from util.util_image import save_img, save_img_xyz, draw_img, draw_img_xyz
from util.util_ris_pattern_2 import point_2_phi_pattern, phase_2_pattern, nRow, eps, phase_2_pattern_xyz, phase_2_bit, \
    phaseBit_2_deg
from util.util_analysis_plane import get_peaks, get_peak_3rd
from util.util_statistics import calculate_statistics


# 配置日志，默认打印到控制台，也可以设置打印到文件
setup_logging()
# setup_logging(log_file="../../files/logs/log_multi_beam_QE.log")
# 获取日志记录器并记录日志
logger = logging.getLogger("[RIS-multi-beam-QE]")


# ============================================= 主函数 ====================================
# 量化选举法: 核心方法 -- N波束
def qe_beam_N(phaseBit_list):
    rows, cols = phaseBit_list[0].shape
    # 创建 phase_mix
    phaseBit_mix = np.zeros((rows, cols))
    random_indices = np.zeros((rows, cols), dtype=int)
    # 将所有的 phaseBit 数组堆叠成一个三维数组
    stacked_phases = np.stack(phaseBit_list, axis=0)
    for i in range(rows):
        for j in range(cols):
            # 对于每个位置 (i, j)，统计各个值出现的次数
            values, counts = np.unique(stacked_phases[:, i, j], return_counts=True)
            # 找出最大出现次数
            max_count = np.max(counts)
            # 找出所有出现次数等于最大出现次数的值
            most_frequent_values = values[counts == max_count]
            # 如果有多个最大出现次数的值，从中随机选择一个
            if len(most_frequent_values) > 1:
                selected_value = np.random.choice(most_frequent_values)
                # 记录选中的值对应的索引
                selected_indices = np.where(stacked_phases[:, i, j] == selected_value)[0]
                random_indices[i, j] = np.random.choice(selected_indices)
            else:
                selected_value = most_frequent_values[0]
                # 记录选中的值对应的索引
                random_indices[i, j] = np.where(stacked_phases[:, i, j] == selected_value)[0][0]
            # 将选中的值赋给 phaseBit_mix
            phaseBit_mix[i, j] = selected_value
    return phaseBit_mix, random_indices


# 量化选举法 -- 双波束
def main_multi_beam_2(theta1, phi1, theta2, phi2, path_pre, bit_num):
    logger.info("main_multi_beam_2: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_2: theta1=%d, phi1=%d, theta2=%d, phi2=%d, " % (theta1, phi1, theta2, phi2))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_N: bit_num bigger than 2.")
        return
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    # 确保 phase1 和 phase2 具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape, "phase1 和 phase2 必须具有相同的形状"
    # QE
    phaseBit_mix, random_indices = qe_beam_N([phaseBit1, phaseBit2])
    phaseBitDeg_mix = phaseBit_2_deg(phaseBit_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save QE multi-beam 2 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)         # 量化选举法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)     # 量化选举法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    save_img(path_pre + "random_indices.jpg", random_indices)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit_mix, path_pre + "phaseBit_mix.csv")
    save_csv(random_indices, path_pre + "random_indices.csv")


# 量化选举法 -- 四波束
def main_multi_beam_4(theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4, path_pre, bit_num):
    logger.info("main_multi_beam_4: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_4: theta1=%d, phi1=%d, theta2=%d, phi2=%d, theta3=%d, phi3=%d, theta4=%d, phi4=%d"
                % (theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_N: bit_num bigger than 2.")
        return
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    phase3, phaseBit3, pattern3 = point_2_phi_pattern(theta3, phi3, bit_num)
    phase4, phaseBit4, pattern4 = point_2_phi_pattern(theta4, phi4, bit_num)
    # 确保所有数组具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape == phaseBit3.shape == phaseBit4.shape, "所有数组必须具有相同的形状"
    # QE
    phaseBit_mix, random_indices = qe_beam_N([phaseBit1, phaseBit2, phaseBit3, phaseBit4])
    phaseBitDeg_mix = phaseBit_2_deg(phaseBit_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save QE multi-beam 4 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phase3.jpg", phase3)
    save_img(path_pre + "phase4.jpg", phase4)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "phaseBit3.jpg", phaseBit3)
    save_img(path_pre + "phaseBit4.jpg", phaseBit4)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "pattern3.jpg", pattern3)
    save_img(path_pre + "pattern4.jpg", pattern4)
    save_img(path_pre + "phase_mix.jpg", phaseBit_mix)       # 量化选举法 -- 结果码阵
    save_img(path_pre + "pattern_mix.jpg", patternBit_mix)   # 量化选举法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    save_img(path_pre + "random_indices.jpg", random_indices)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phase3, path_pre + "phase3.csv")
    save_csv(phase4, path_pre + "phase4.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit3, path_pre + "phaseBit3.csv")
    save_csv(phaseBit4, path_pre + "phaseBit4.csv")
    save_csv(phaseBit_mix, path_pre + "phase_mix.csv")
    save_csv(random_indices, path_pre + "random_indices.csv")


# 八波束
def main_multi_beam_8(theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
                          theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8,
                          path_pre, bit_num):
    logger.info("main_multi_beam_8: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_8: theta1=%d, phi1=%d, theta2=%d, phi2=%d, theta3=%d, phi3=%d, theta4=%d, phi4=%d, "
                "theta5=%d, phi5=%d, theta6=%d, phi6=%d, theta7=%d, phi7=%d, theta8=%d, phi8=%d"
                % (theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
                   theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_8: bit_num bigger than 2.")
        return
    # 获取所有的 phaseBit 变量
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    phase3, phaseBit3, pattern3 = point_2_phi_pattern(theta3, phi3, bit_num)
    phase4, phaseBit4, pattern4 = point_2_phi_pattern(theta4, phi4, bit_num)
    phase5, phaseBit5, pattern5 = point_2_phi_pattern(theta5, phi5, bit_num)
    phase6, phaseBit6, pattern6 = point_2_phi_pattern(theta6, phi6, bit_num)
    phase7, phaseBit7, pattern7 = point_2_phi_pattern(theta7, phi7, bit_num)
    phase8, phaseBit8, pattern8 = point_2_phi_pattern(theta8, phi8, bit_num)
    # 确保所有数组具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape == phaseBit3.shape == phaseBit4.shape == \
           phaseBit5.shape == phaseBit6.shape == phaseBit7.shape == phaseBit8.shape, "所有数组必须具有相同的形状"
    # QE
    phaseBit_mix, random_indices = qe_beam_N([phaseBit1, phaseBit2, phaseBit3, phaseBit4,
                                              phaseBit5, phaseBit6, phaseBit7, phaseBit8])
    phaseBitDeg_mix = phaseBit_2_deg(phaseBit_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save QE multi-beam 8 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phase3.jpg", phase3)
    save_img(path_pre + "phase4.jpg", phase4)
    save_img(path_pre + "phase5.jpg", phase5)
    save_img(path_pre + "phase6.jpg", phase6)
    save_img(path_pre + "phase7.jpg", phase7)
    save_img(path_pre + "phase8.jpg", phase8)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "phaseBit3.jpg", phaseBit3)
    save_img(path_pre + "phaseBit4.jpg", phaseBit4)
    save_img(path_pre + "phaseBit5.jpg", phaseBit5)
    save_img(path_pre + "phaseBit6.jpg", phaseBit6)
    save_img(path_pre + "phaseBit7.jpg", phaseBit7)
    save_img(path_pre + "phaseBit8.jpg", phaseBit8)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "pattern3.jpg", pattern3)
    save_img(path_pre + "pattern4.jpg", pattern4)
    save_img(path_pre + "pattern5.jpg", pattern5)
    save_img(path_pre + "pattern6.jpg", pattern6)
    save_img(path_pre + "pattern7.jpg", pattern7)
    save_img(path_pre + "pattern8.jpg", pattern8)
    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)  # 量化选举法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)  # 量化选举法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    save_img(path_pre + "random_indices.jpg", random_indices)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phase3, path_pre + "phase3.csv")
    save_csv(phase4, path_pre + "phase4.csv")
    save_csv(phase5, path_pre + "phase5.csv")
    save_csv(phase6, path_pre + "phase6.csv")
    save_csv(phase7, path_pre + "phase7.csv")
    save_csv(phase8, path_pre + "phase8.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit3, path_pre + "phaseBit3.csv")
    save_csv(phaseBit4, path_pre + "phaseBit4.csv")
    save_csv(phaseBit5, path_pre + "phaseBit5.csv")
    save_csv(phaseBit6, path_pre + "phaseBit6.csv")
    save_csv(phaseBit7, path_pre + "phaseBit7.csv")
    save_csv(phaseBit8, path_pre + "phaseBit8.csv")
    save_csv(phaseBit_mix, path_pre + "phaseBit_mix.csv")
    save_csv(random_indices, path_pre + "random_indices.csv")


# 十六波束
def main_multi_beam_16(theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
                           theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8,
                           theta9, phi9, theta10, phi10, theta11, phi11, theta12, phi12,
                           theta13, phi13, theta14, phi14, theta15, phi15, theta16, phi16,
                           path_pre, bit_num):
    logger.info("main_multi_beam_16: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info(
        "main_multi_beam_16: theta1=%d, phi1=%d, theta2=%d, phi2=%d, theta3=%d, phi3=%d, theta4=%d, phi4=%d, "
        "theta5=%d, phi5=%d, theta6=%d, phi6=%d, theta7=%d, phi7=%d, theta8=%d, phi8=%d"
        % (theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
           theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8))
    logger.info(
        "main_multi_beam_16: theta9=%d, phi9=%d, theta10=%d, phi10=%d, theta11=%d, phi11=%d, theta12=%d, phi12=%d, "
        "theta13=%d, phi13=%d, theta14=%d, phi14=%d, theta15=%d, phi15=%d, theta16=%d, phi16=%d"
        % (theta9, phi9, theta10, phi10, theta11, phi11, theta12, phi12, theta13, phi13, theta14, phi14,
           theta15, phi15, theta16, phi16))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_16: bit_num bigger than 2.")
        return
    # 获取所有的 phaseBit 变量
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    phase3, phaseBit3, pattern3 = point_2_phi_pattern(theta3, phi3, bit_num)
    phase4, phaseBit4, pattern4 = point_2_phi_pattern(theta4, phi4, bit_num)
    phase5, phaseBit5, pattern5 = point_2_phi_pattern(theta5, phi5, bit_num)
    phase6, phaseBit6, pattern6 = point_2_phi_pattern(theta6, phi6, bit_num)
    phase7, phaseBit7, pattern7 = point_2_phi_pattern(theta7, phi7, bit_num)
    phase8, phaseBit8, pattern8 = point_2_phi_pattern(theta8, phi8, bit_num)
    phase9, phaseBit9, pattern9 = point_2_phi_pattern(theta9, phi9, bit_num)
    phase10, phaseBit10, pattern10 = point_2_phi_pattern(theta10, phi10, bit_num)
    phase11, phaseBit11, pattern11 = point_2_phi_pattern(theta11, phi11, bit_num)
    phase12, phaseBit12, pattern12 = point_2_phi_pattern(theta12, phi12, bit_num)
    phase13, phaseBit13, pattern13 = point_2_phi_pattern(theta13, phi13, bit_num)
    phase14, phaseBit14, pattern14 = point_2_phi_pattern(theta14, phi14, bit_num)
    phase15, phaseBit15, pattern15 = point_2_phi_pattern(theta15, phi15, bit_num)
    phase16, phaseBit16, pattern16 = point_2_phi_pattern(theta16, phi16, bit_num)
    # 确保所有数组具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape == phaseBit3.shape == phaseBit4.shape == \
           phaseBit5.shape == phaseBit6.shape == phaseBit7.shape == phaseBit8.shape == \
           phaseBit9.shape == phaseBit10.shape == phaseBit11.shape == phaseBit12.shape == \
           phaseBit13.shape == phaseBit14.shape == phaseBit15.shape == phaseBit16.shape, "所有数组必须具有相同的形状"
    # QE
    phaseBit_mix, random_indices = qe_beam_N([phaseBit1, phaseBit2, phaseBit3, phaseBit4,
                                              phaseBit5, phaseBit6, phaseBit7, phaseBit8,
                                              phaseBit9, phaseBit10, phaseBit11, phaseBit12,
                                              phaseBit13, phaseBit14, phaseBit15, phaseBit16])
    phaseBitDeg_mix = phaseBit_2_deg(phaseBit_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save QE multi-beam 16 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    for i in range(1, 17):
        save_img(path_pre + f"phase{i}.jpg", eval(f"phase{i}"))
        save_img(path_pre + f"phaseBit{i}.jpg", eval(f"phaseBit{i}"))
        save_img(path_pre + f"pattern{i}.jpg", eval(f"pattern{i}"))

    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)  # 量化选举法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)  # 量化选举法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    save_img(path_pre + "random_indices.jpg", random_indices)
    # 保存相位结果
    for i in range(1, 17):
        save_csv(eval(f"phase{i}"), path_pre + f"phase{i}.csv")
        save_csv(eval(f"phaseBit{i}"), path_pre + f"phaseBit{i}.csv")
    save_csv(phaseBit_mix, path_pre + "phaseBit_mix.csv")
    save_csv(random_indices, path_pre + "random_indices.csv")


# 量化选举法 -- N波束(均分, 非分块)
def main_multi_beam_N(points, path_pre, bit_num):
    logger.info("QE.main_multi_beam_N: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("QE.main_multi_beam_N: num of points = %d" % (len(points)))
    logger.info("QE.main_multi_beam_N: points = %s" % (points))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_N: bit_num bigger than 2.")
        return
    phase_pattern_list = []
    phaseBit_list = []
    for point in points:
        theta = point[0]
        phi = point[1]
        phase, phaseBit, pattern = point_2_phi_pattern(theta, phi, bit_num)
        phase_pattern_list.append([phase, phaseBit, pattern])
        phaseBit_list.append(phaseBit)
    # QE
    phaseBit_mix, random_indices = qe_beam_N(phaseBit_list)
    phaseBitDeg_mix = phaseBit_2_deg(phaseBit_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save QE multi-beam N result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存结果
    for i in range(len(phase_pattern_list)):
        phase = phase_pattern_list[i][0]
        phaseBit = phase_pattern_list[i][1]
        pattern = phase_pattern_list[i][2]
        # 保存图片
        save_img(path_pre + "phase" + str(i+1) + ".jpg", phase)
        save_img(path_pre + "phaseBit" + str(i+1) + ".jpg", phaseBit)
        save_img(path_pre + "pattern" + str(i+1) + ".jpg", pattern)
        # 保存相位结果
        save_csv(phase, path_pre + "phase" + str(i+1) + ".csv")
        save_csv(phaseBit, path_pre + "phaseBit" + str(i+1) + ".csv")
    # 保存图片
    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)       # 量化选举法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)   # 量化选举法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    save_img(path_pre + "random_indices.jpg", random_indices)
    # 保存相位结果
    save_csv(phaseBit_mix, path_pre + "phase_mix.csv")
    save_csv(random_indices, path_pre + "random_indices.csv")


# ======================================================= 测试方法 ====================================================
def test_qe_beam_N():
    phaseBit_list = []
    phase1 = [[1, 2, 3], [1, 2, 3], [1, 2, 1]]
    phase2 = [[2, 2, 3], [1, 2, 3], [1, 1, 3]]
    phase3 = [[1, 2, 1], [2, 1, 1], [2, 1, 1]]
    phase4 = [[1, 2, 1], [2, 1, 3], [2, 2, 3]]
    phaseBit_list.append(np.array(phase1))
    phaseBit_list.append(np.array(phase2))
    phaseBit_list.append(np.array(phase3))
    phaseBit_list.append(np.array(phase4))
    phaseBit_mix, random_indices = qe_beam_N(phaseBit_list)
    print(phaseBit_mix)
    print(random_indices)


# ======================================================= main 主方法 ===============================================
def main_multi_qe():
    # 基于QE的方法: 主函数
    # 量化选举法: 主函数
    # main_multi_beam_2(30, 0, 30, 90,
    #                   "../files/multi-beam/1bit/QE/2-(30,0,30,90)/", 1)
    # main_multi_beam_2(30, 0, 30, 180,
    #                   "../files/multi-beam/1bit/QE/2-(30,0,30,180)/", 1)
    # main_multi_beam_4(30, 0, 30, 60, 30, 120, 30, 180,
    #                   "../files/multi-beam/1bit/QE/4-(30,0,30,60,30,120,30,180)/", 1)
    # main_multi_beam_4(30, 0, 30, 90, 30, 180, 30, 270,
    #                   "../files/multi-beam/1bit/QE/4-(30,0,30,90,30,180,30,270)/", 1)
    # main_multi_beam_8(30, 0, 30, 45, 30, 90, 30, 135, 30, 180, 30, 225, 30, 270, 30, 315,
    #                   "../files/multi-beam/1bit/QE/8-(30,45step)/", 1)
    # main_multi_beam_16(30, 0, 30, 22.5, 30, 45, 30, 67.5, 30, 90, 30, 112.5, 30, 135, 30, 157.5,
    #                    30, 180, 30, 202.5, 30, 225, 30, 247.5, 30, 270, 30, 292.5, 30, 315, 30, 337.5,
    #                    "../files/multi-beam/1bit/QE/16-(30,22.5step)/", 1)
    # #
    # main_multi_beam_2(30, 0, 30, 90,
    #                   "../files/multi-beam/2bit/QE/2-(30,0,30,90)/", 2)
    # main_multi_beam_2(30, 0, 30, 180,
    #                   "../files/multi-beam/2bit/QE/2-(30,0,30,180)/", 2)
    # main_multi_beam_4(30, 0, 30, 60, 30, 120, 30, 180,
    #                   "../files/multi-beam/2bit/QE/4-(30,0,30,60,30,120,30,180)/", 2)
    # main_multi_beam_4(30, 0, 30, 90, 30, 180, 30, 270,
    #                   "../files/multi-beam/2bit/QE/4-(30,0,30,90,30,180,30,270)/", 2)
    # main_multi_beam_8(30, 0, 30, 45, 30, 90, 30, 135, 30, 180, 30, 225, 30, 270, 30, 315,
    #                   "../files/multi-beam/2bit/QE/8-(30,45step)/", 2)
    # main_multi_beam_16(30, 0, 30, 22.5, 30, 45, 30, 67.5, 30, 90, 30, 112.5, 30, 135, 30, 157.5,
    #                    30, 180, 30, 202.5, 30, 225, 30, 247.5, 30, 270, 30, 292.5, 30, 315, 30, 337.5,
    #                    "../files/multi-beam/2bit/QE/16-(30,22.5step)/", 2)
    #
    # main_multi_beam_N([[30, 0], [30, 180]],
    #                   "../files/multi-beam/1bit/QE/B-2-(30,0,30,180)/", 1)
    # main_multi_beam_N([[30, 0], [30, 90]],
    #                   "../files/multi-beam/1bit/QE/B-2-(30,0,30,90)/", 1)
    # main_multi_beam_N([[30, 0], [30, 60], [30, 120], [30, 180]],
    #                   "../files/multi-beam/1bit/QE/B-4-(30,0,30,60,30,120,30,180)/", 1)
    # main_multi_beam_N([[30, 0], [30, 90], [30, 180], [30, 270]],
    #                   "../files/multi-beam/1bit/QE/B-4-(30,0,30,90,30,180,30,270)/", 1)
    main_multi_beam_N([[30, 0], [30, 45], [30, 90], [30, 135], [30, 180], [30, 225], [30, 270], [30, 315]],
                      "../files/multi-beam/1bit/QE/B-8-(30,45step)/", 1)
    #
    main_multi_beam_N([[30, 0], [30, 180]],
                      "../files/multi-beam/2bit/QE/B-2-(30,0,30,180)/", 2)
    main_multi_beam_N([[30, 0], [30, 90]],
                      "../files/multi-beam/2bit/QE/B-2-(30,0,30,90)/", 2)
    main_multi_beam_N([[30, 0], [30, 60], [30, 120], [30, 180]],
                      "../files/multi-beam/2bit/QE/B-4-(30,0,30,60,30,120,30,180)/", 2)
    main_multi_beam_N([[30, 0], [30, 90], [30, 180], [30, 270]],
                      "../files/multi-beam/2bit/QE/B-4-(30,0,30,90,30,180,30,270)/", 2)
    main_multi_beam_N([[30, 0], [30, 45], [30, 90], [30, 135], [30, 180], [30, 225], [30, 270], [30, 315]],
                      "../files/multi-beam/2bit/QE/B-8-(30,45step)/", 2)






if __name__ == '__main__':
    logger.info("1bit-RIS-multi-beam-QE: Geometric partitioning method")
    # test_qe_beam_N()
    main_multi_qe()